package com.enlf.service.impl;

import com.enlf.config.RedissonConfig;
import com.enlf.dto.Result;
import com.enlf.entity.SeckillVoucher;
import com.enlf.entity.VoucherOrder;
import com.enlf.mapper.SeckillVoucherMapper;
import com.enlf.mapper.VoucherOrderMapper;
import com.enlf.service.ISeckillVoucherService;
import com.enlf.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.enlf.utils.IdWork;
import com.enlf.utils.UserHolder;
import com.enlf.utils.lock.SimpleRedisLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.client.RedisClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author renge
 * @since 2023-9-11
 */
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    @Resource
    private ISeckillVoucherService iSeckillVoucherService;

    @Resource
    private IdWork idWork;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 实现秒杀下单
     *
     * @param voucherId
     * @return
     */
    @Override
    public Result saveSeckillVoucher(Long voucherId) {
        //1.查询优惠卷
        SeckillVoucher seckillVoucher = iSeckillVoucherService.getById(voucherId);
        //2.判断是否开始
        if (seckillVoucher.getBeginTime().isAfter(LocalDateTime.now())) {
            //如果还没开始 返回错误
            return Result.fail("秒杀尚未开始！");
        }
        //3.判断是否结束
        if (seckillVoucher.getEndTime().isBefore(LocalDateTime.now())) {
            return Result.fail("秒杀已经结束！");
        }
        //4.判断库存是否充足
        if (seckillVoucher.getStock() < 1) {
            //库存不足
            return Result.fail("库存不足");
        }
        //5.实现一人一单
        Long userID = UserHolder.getUser().getId();
        //每一次的sync的id在toString底层都是new一个新的String对象，因此不行
        //intern方法返回字符串的规范表示，当用户一样时锁就一样
        //synchronized (userID.toString().intern()) {
            //先提交事务再释放锁
            //spring事务，this拿到的是非动态代理
            //获取代理对象(事务)
        //6.获取分布式锁
//        SimpleRedisLock simpleRedisLock = new SimpleRedisLock(stringRedisTemplate, "order:" + userID);
        RLock lock = redissonClient.getLock("lock:order:" + userID);
        //默认30s
        boolean isLock = lock.tryLock();
        if (!isLock){
            return Result.fail("用户不可重复下单");
        }
        try {
            //这个调用会通过代理，因此会应用 AOP 增强 ，保证事务
            IVoucherOrderService proxy = (IVoucherOrderService) AopContext. currentProxy();
            return proxy.createVoucherOrder(voucherId);
        } finally {
            //释放锁
            lock.unlock();
        }

    }

    @Transactional
    public Result createVoucherOrder(Long voucherId) {
        Long userID = UserHolder.getUser().getId();
        //5.1查询订单
        Integer count = query().eq("user_id", userID).eq("voucher_id", voucherId).count();
        //判断是否购买过
        if (count > 0) {
            //该用户已经购买过
            return Result.fail("用户已经购买过一次!");
        }
        //6.扣减库存
        boolean success = iSeckillVoucherService.update()
                .setSql("stock = stock - 1")// set stock = stock -1
                .eq("voucher_id", voucherId)
                //通过乐观锁 将库存作为版本号，每次更新时都会再次查询库存检查库存是大于0就可以
                .gt("stock", 0)//where id = ? and stock = ?
                .update();
        if (!success) {
            return Result.fail("库存不足");
        }
        //7.创建订单
        VoucherOrder voucherOrder = new VoucherOrder();
        //7.1 订单id
        long orderId = idWork.nextID("order");
        voucherOrder.setId(orderId);
        //7.2 用户id
        voucherOrder.setUserId(userID);
        //7.3 优惠卷id
        voucherOrder.setVoucherId(voucherId);
        save(voucherOrder);

        return Result.ok(orderId);


    }
}

/* //1.查询优惠卷
        SeckillVoucher seckillVoucher = iSeckillVoucherService.getById(voucherId);
        //2.判断是否开始
        if (seckillVoucher.getBeginTime().isAfter(LocalDateTime.now())) {
            //如果还没开始 返回错误
            return Result.fail("秒杀尚未开始！");
        }
        //3.判断是否结束
        if (seckillVoucher.getEndTime().isBefore(LocalDateTime.now())){
            return Result.fail("秒杀已经结束！");
        }
        //4.判断库存是否充足
        if (seckillVoucher.getStock()<1){
            //库存不足
            return Result.fail("库存不足");
        }
        //5.扣减库存
        boolean success = iSeckillVoucherService.update()
                .setSql("stock = stock - 1")// set stock = stock -1
                .eq("voucher_id", voucherId)
                //通过乐观锁 将库存作为版本号，每次更新时都会再次查询库存检查库存是大于0就可以
                .gt("stock",0)//where id = ? and stock = ?
                .update();
        if (!success){
            return Result.fail("库存不足");
        }
        //6.创建订单
        VoucherOrder voucherOrder = new VoucherOrder();
        //6.1 订单id
        long orderId = idWork.nextID("order");
        voucherOrder.setId(orderId);
        //6.2 用户id
        Long userID = UserHolder.getUser().getId();
        voucherOrder.setUserId(userID);
        //6.3 优惠卷id
        voucherOrder.setVoucherId(voucherId);
        save(voucherOrder);
        return Result.ok(orderId);*/
